package com.shadow.study.quartz.quartz;

import com.shadow.common.entity.ScheduleJobEntity;
import com.shadow.common.entity.ScheduleJobLogEntity;
import com.shadow.common.utils.SpringContextUtils;
import com.shadow.service.ScheduleJobLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 任务执行调用和日志记录.
 * @author Pbody
 * @since 2021/3/23 10:20
 */
@Slf4j
public class ScheduleJob extends QuartzJobBean {

    private static final int MAX_LENGTH = 2000;
    private final ExecutorService service = Executors.newSingleThreadExecutor();

    /**
     * 任务执行.
     * @param context job上下文对象
     * @author Pbody
     * @date 13:42 2021/7/27
     **/
    @Override
    protected void executeInternal(final JobExecutionContext context) throws JobExecutionException {
        ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap()
                .get(ScheduleUtils.JOB_PARAM_KEY);
        //获取spring bean
        ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean("scheduleJobLogService");
        //数据库保存执行记录
        ScheduleJobLogEntity scheduleJobLogEntity = new ScheduleJobLogEntity();
        scheduleJobLogEntity.setJobId(scheduleJob.getId());
        scheduleJobLogEntity.setBeanName(scheduleJob.getBeanName());
        scheduleJobLogEntity.setMethodName(scheduleJob.getMethodName());
        scheduleJobLogEntity.setParams(scheduleJob.getParams());
        //任务开始时间
        long startTime = System.currentTimeMillis();
        try {
            //执行任务
            log.info("任务准备执行，任务ID{}", scheduleJob.getId());
            ScheduleRunnable task = new ScheduleRunnable(scheduleJob.getBeanName(),
                    scheduleJob.getMethodName(), scheduleJob.getParams());
            Future<?> future = service.submit(task);
            future.get();
            //任务执行总时长
            long times = System.currentTimeMillis() - startTime;
            scheduleJobLogEntity.setTimes((int) times);
            //任务状态    1：成功    0：失败
            scheduleJobLogEntity.setStatus(1);
            log.info("任务执行完毕，{}任务ID，总共耗时：{}毫秒", scheduleJob.getId(), times);
        } catch (ExecutionException | NoSuchMethodException | InterruptedException e) {
            log.error("任务执行失败，{}任务ID", scheduleJob.getId(), e);
            //任务执行总时长
            long times = System.currentTimeMillis() - startTime;
            scheduleJobLogEntity.setTimes((int) times);
            scheduleJobLogEntity.setStatus(0);
            scheduleJobLogEntity.setError(StringUtils.substring(e.getMessage(), 0, MAX_LENGTH));
            Thread.currentThread().interrupt();
        } finally {
            scheduleJobLogService.save(scheduleJobLogEntity);
        }
    }
}
